# -*- coding: utf-8 -*- 
# Virtual Router Simulator 
#
# Copyright (C) 2009-2010 VRSim Project
# Author: Choonho Son <choonho@kt.com>
# URL: <http://vrsim.googlecode.com>
# For license information, see LICENSE.TXT
#

import os

import VRSim.Globals as globals
from PyQt4 import QtSvg,  QtGui,  QtCore
from PyQt4.QtGui import QMainWindow,  QAction,  QActionGroup,  QIcon
from VRSim.Ui.Ui_MainWindow import Ui_MainWindow
from VRSim.Ui.Project import Project
from VRSim.Ui.About import About

from VRSim.Node.XML import XML
from VRSim.Utils import debug,  message,  parsePath

from VRSim.Help import HelpForm

class Workspace(QMainWindow, Ui_MainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.submenu_Docks = QtGui.QMenu()
        Ui_MainWindow.setupUi(self,  self)
        
        # Title
        # window title
        title = "KT-VNS (Version %s)" % globals.STRVER
        self.setWindowTitle(title)
            
        # default disable
        if globals.GApp.authenticated == False:
            self.setDisabled(True)
            
        self.__createMenus()
        self.__connectActions()
        
        self.flg_showHostname = True
          
        #self.statusBar.showMessage("Running....")
    def __createMenus(self):
        # create progress bar
        self.status_userid = QtGui.QLabel()
        self.status_message = QtGui.QLabel()
        #self.status_progress = QtGui.QProgressBar()
        self.connected = QtGui.QPixmap(":/symbols/config/connected.gif")
        self.disconnedted = QtGui.QPixmap(":/symbols/config/disconnected.gif")
        statusIcon = QtGui.QIcon(self.connected)
        self.statusButton = QtGui.QPushButton()
        self.statusButton.setIcon(statusIcon)
        
        self.status_message.setText("message")
        self.statusBar.addPermanentWidget(self.status_userid)
        self.statusBar.addPermanentWidget(self.status_message)
        self.statusBar.addPermanentWidget(self.statusButton)
        #self.statusBar.addPermanentWidget(self.status_progress)
        
        # init progress
        #self.status_progress.setMinimum(0)
        #self.status_progress.setMaximum(0)
        #self.status_progress.setGeometry(1, 1, 10, 5)

    def __connectActions(self):
        # file
        self.connect(self.action_New_Project,  QtCore.SIGNAL('triggered()'),  self.__action_new)
        self.connect(self.action_Open,  QtCore.SIGNAL('triggered()'),  self.__action_open)
        self.connect(self.action_Save,  QtCore.SIGNAL('triggered()'),  self.__action_save)
        self.connect(self.actionSave_As,  QtCore.SIGNAL('triggered()'),  self.__action_save_as)
        
        # edit
        self.connect(self.action_Hypervisors,  QtCore.SIGNAL('triggered()'),  self.__action_hypervisors)
        self.connect(self.action_Font,  QtCore.SIGNAL('triggered()'),  self.__action_Font)
        self.connect(self.action_Preference,  QtCore.SIGNAL('triggered()'),  self.__action_preference)
        
        
        self.connect(self.action_Add_link,  QtCore.SIGNAL('triggered()'),  self.__action_addLink)
        
        # view
        self.connect(self.actionZoom_In,  QtCore.SIGNAL('triggered()'),  self.__action_ZoomIn)
        self.connect(self.actionZoom_Out,  QtCore.SIGNAL('triggered()'),  self.__action_ZoomOut)
        self.connect(self.actionZoom_1_1,  QtCore.SIGNAL('triggered()'),  self.__action_Zoom1_1)
        self.connect(self.actionNode_Types,  QtCore.SIGNAL('toggled(bool)'),  self.dockWidget_NodeTypes.setVisible)
        #self.connect(self.dockWidget_NodeTypes,  QtCore.SIGNAL('visibilityChanged(bool)'),  self.actionNode_Types.setChecked)
        self.connect(self.actionSummary,  QtCore.SIGNAL('toggled(bool)'),  self.dockWidget_Summary.setVisible)
        #self.connect(self.dockWidget_Summary,  QtCore.SIGNAL('visibilityChanged(bool)'),  self.actionSummary.setChecked)
        
        # start, stop, suspend
        self.connect(self.action_Start,  QtCore.SIGNAL('triggered()'),  self.__action_Start)
        self.connect(self.action_Stop,  QtCore.SIGNAL('triggered()'),  self.__action_Stop)
        self.connect(self.action_Suspend,  QtCore.SIGNAL('triggered()'), self.__action_Suspend)
        
        # help
        self.connect(self.action_Online_Help,  QtCore.SIGNAL('triggered()'),  self.__action_Help)
        self.connect(self.action_About,  QtCore.SIGNAL('triggered()'),  self.__action_About)
        
        # exit
        self.connect(self.action_Quit,  QtCore.SIGNAL('triggered()'),  self.close)
        
        
    def retranslateUi(self,  MainWindow):
        Ui_MainWindow.retranslateUi(self,  MainWindow)
        
        try:
            self.nodesDock.retranslateUi(self.nodesDock)
        
        except Exception,  e:
            pass
            
        
        
    #################
    # Actions
    #################
    def __action_new(self):
        cfg = Project()
        cfg.show()
        cfg.exec_()
        # open project config window
        #globals.GApp.xml.newTopology()
        
    def __action_open(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, "Open Topology Config file",  "./", "XML files (*.xml)")
        msg = "Load file name: %s" % filename
        globals.GApp.my_logger.debug(msg)
        globals.GApp.scene.loadXML(filename)
        
    # Save the topolgoy config file
    # check config file name exist
    def __action_save(self):
        xml = globals.GApp.topology.getXML()
        globals.GApp.my_logger.debug(xml.toprettyxml())
        if globals.saveFilename != "":
            filename = globals.saveFilename
        else:
            filename = QtGui.QFileDialog.getSaveFileName(self,  "Save Topology Config file",  "./",  "XML files (*.xml)")
            
        filename_en = unicode(filename).encode(globals.ENCODING)
        print filename_en
        try:
            fp = open(filename_en,  "w")
            msg = globals.eventMsg["__action_save"]
            nmsg = msg % filename
            globals.GApp.mainWindow.NodesLog.addEvent(nmsg)
        except:
            
            msg = globals.errorMsg["__action_save"]
            nmsg = msg % filename
            globals.GApp.mainWindow.NodesLog.addError(nmsg)
            return False
            
        fp.write(xml.toxml('UTF-8'))
        #print globals.GApp.topology.printXML()
        fp.close()
            
    # Save a topology config file    
    def __action_save_as(self):
        xml = globals.GApp.topology.getXML()
        filename = QtGui.QFileDialog.getSaveFileName(self,  "Save Topology Config file",  "/",  "XML files (*.xml)")
        # encoding to client system (windows euc-kr)
        filename_en = unicode(filename).encode(globals.ENCODING)
        try:
            fp = open(filename_en,  "w")
            fp.write(xml.toxml('UTF-8'))
            #print globals.GApp.topology.printXML()
            fp.close()
            msg = globals.eventMsg["__action_saveas"]
            nmsg = msg % filename
            globals.GApp.mainWindow.NodesLog.addEvent(nmsg)
        except:
            msg = globals.errorMsg["__action_saveas"]
            nmsg = msg % filename
            globals.GApp.mainWindow.NodesLog.addError(nmsg)
    
    def __action_hypervisors(self):
        cfg = Project(2)
        cfg.show()
        cfg.exec_()
      
        
    def __action_Font(self):
        font,  ok = QtGui.QFontDialog.getFont()
        if ok:
            globals.GApp.mainWindow.setFont(font)
        
    def __action_preference(self):
        cfg = Project()
        cfg.show()
        cfg.exec_()

    def __action_addLink(self):
        if not self.action_Add_link.isChecked():
            self.action_Add_link.setText('Add a link')
            globals.addingLinkFlag = False
            globals.GApp.scene.resetAddingLink()
            globals.GApp.scene.setCursor(QtCore.Qt.ArrowCursor)
        
        else:
            menu = QtGui.QMenu()
            linktypes = globals.linkTypes.keys()
            linktypes.sort()
            for linktype in linktypes:
                menu.addAction(linktype)
            menu.connect(menu,  QtCore.SIGNAL("triggered(QAction *)"),  self.__setLinkType)
            menu.exec_(QtGui.QCursor.pos())
            
            globals.addingLinkFlag = True
            # change "Add a link" to "Ethernet" ....
            self.action_Add_link.setText(globals.linkTypes_string[globals.currentLinkType])
            globals.GApp.scene.setCursor(QtCore.Qt.CrossCursor)
        
    def __setLinkType(selfself,  action):
        action = str(action.text())
        globals.currentLinkType = globals.linkTypes[action] 
        
    # Zoom operation
    def __action_ZoomIn(self):
        factor_in = pow(2.0,  120 / 240.0)
        globals.GApp.scene.scaleView(factor_in)
        
    def __action_ZoomOut(self):
        factor_out = pow(2.0,  -120 / 240.0)
        globals.GApp.scene.scaleView(factor_out)
        
    def __action_Zoom1_1(self):
        globals.GApp.scene.resetMatrix()
     
    def __action_Start(self):
        if globals.GApp.scene:
            globals.GApp.scene.slotStartNode()
        
    def __action_Stop(self):
        if globals.GApp.scene:
            globals.GApp.scene.slotStopNode()
        
    def __action_Suspend(self):
        if globals.GApp.scene:
            globals.GApp.scene.slotSuspendNode()
        
    def __action_About(self):
        abt = About()
        abt.show()
        abt.exec_()
    
    def __action_Help(self):
        form = HelpForm.HelpForm(self)
        form.show()
        
            
    # overwrite closeEvent
    def closeEvent(self,  event):
        debug("close event")
        
        # ASK for close, stop all virtual machines
        msg = "Stop All virtual machines and close?"
        ret = message(msg,  "question")
        if ret == False:
            # does not want to exit!
            event.ignore()
            return False
        
        
        nodes = globals.GApp.topology.nodes
        # close running virtual machine
        stopList = []
        for nodeid in nodes:
            node = globals.GApp.topology.nodes[nodeid]
            state = node.physnode.state
            if state == globals.START or state== globals.SUSPEND:
                stopList.append(node)
                #node.stop()
        if len(stopList) > 0:
            message("Stop all virtual machines")
            for node in stopList:
                node.stop()
        
        # relese resource of VMAPI
        vmapi = globals.GApp.topology.vmapi
        for keys in vmapi:
            msg = "Release Resource : %s" %  keys
            message(msg)
            inst = vmapi[keys]
            inst.releaseResource()
         
